
import paypalrestsdk
import os
from  vsogame.gateway_sdk.datastructure import SignResponse, VerifyResponse
from  vsogame.gateway_sdk.exception import PaymentException
import logging
mode = 'live' if os.getenv('ENV') == 'production' else 'sandbox'

logger = logging.getLogger(__name__)

_cached_apis = {}


def _get_api(gateway_ext):
    client_id = gateway_ext.get('client_id', None)
    client_secret = gateway_ext.get('client_secret', None)

    if not client_id or not client_secret:
        raise PaymentException(reason='no client_id  or client_secret configured.')
    else:
        client_id = client_id.strip()
        client_secret = client_secret.strip()

    api_key = '{}-{}'.format(client_id, client_secret)
    api = _cached_apis.get(api_key, None)
    if not api:
        api = paypalrestsdk.Api(client_id=client_id, client_secret=client_secret)
        _cached_apis[api_key] = api
    return api


def _parse_payment_result(payment):
    verify_response = VerifyResponse(True)
    verify_response.trade_code = payment.id
    verify_response.return_info = payment.state

    transactions = payment.transactions

    if transactions:
        transaction = transactions[0]
        verify_response.amount = transaction.amount.total

        related_resources = transaction.related_resources

        if related_resources:
            sale = related_resources[0].sale
            transaction_fee = sale.transaction_fee
            if transaction_fee:
                verify_response.fee = transaction_fee.value
    return verify_response


def verify(request):
    try:
        gateway_ext = request.gateway_ext

        api = _get_api(gateway_ext)

        payment_id = request.options.get('paymentId')

        payer_id = request.options.get('token')

        payment = paypalrestsdk.Payment.find(payment_id, api=api)

        if not payment_id or not payer_id:
            raise PaymentException(reason='args error. must  payment_id  and  payer_id')
        if payment:
            if payment.state == 'created':
                payer_info = payment.payer.payer_info
                if payment.execute({'payer_id': payer_info.payer_id}):
                    if payment.state == 'approved':
                        return _parse_payment_result(payment)
                    else:
                        raise PaymentException(reason=payment.error)
                else:
                    # 执行失败
                    logger.error('[execute failed. reason :%s]', payment.error)
                    raise PaymentException(reason=payment.error)
            elif payment.state == 'approved':
                return _parse_payment_result(payment)

            else:
                raise PaymentException(reason='[payment state not right.]')
        else:
            raise ('[verify failed. not found payment : %s]', payment_id)
    except PaymentException as pe:
        verify_response = VerifyResponse(False, error_message=pe.reason)
        return verify_response


def sign(request):
    gateway_ext = request.gateway_ext

    api = _get_api(gateway_ext)
    links = request.links

    payment = paypalrestsdk.Payment({
        "intent": "sale",
        "payer": {
            "payment_method": "paypal"
        },
        "redirect_urls": {
            "return_url": links.get('verify', ''),
            "cancel_url": links.get('cancel', '')
        },
        "transactions": [{
            "item_list": {
                "items": [
                    {
                        "name": 'test',
                        "sku": "cdk",
                        "price": request.amount,
                        "currency": 'USD',
                        "quantity": 1
                    }

                ]
            },

            "amount": {
                "total": request.amount,
                "currency": "USD"
                # "currency": request.currency
            },
            "description": 'text',  # request.description
        }]

    }, api=api)

    if payment.create():
        sign_response = SignResponse(True)
        sign_response.trade_code = payment.id

        print("Payment[%s] created successfully" % (payment.id))
        for link in payment.links:
            if link.method == "REDIRECT":
                # Convert to str to avoid google appengine unicode issue
                # https://github.com/paypal/rest-api-sdk-python/pull/58
                redirect_url = str(link.href)
                sign_response.post_url = redirect_url

                sign_response.approval_url.href = str(link.href)
                sign_response.approval_url.method = 'REDIRECT'
                # sign_response.create_time  =
                print("Redirect for approval: %s" % (redirect_url))
    else:
        sign_response = SignResponse(False)
        sign_response.success = False
        sign_response.message = payment.error
        print("Error while creating payment:")
        print(payment.error)
    return sign_response
